package cn.cq.admin.service.impl;

import cn.cq.admin.entity.dto.RoleDto;
import cn.cq.admin.entity.dto.RolePageDto;
import cn.cq.admin.entity.model.TRoleResource;
import cn.cq.admin.entity.model.TUser;
import cn.cq.admin.entity.vo.RoleVo;
import cn.cq.admin.service.TRoleResourceService;
import cn.cq.admin.service.TUserService;
import cn.dev33.satoken.util.SaResult;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.cq.admin.entity.model.TRole;
import cn.cq.admin.service.TRoleService;
import cn.cq.admin.mapper.TRoleMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author dicraft
 * @description 针对表【t_role(角色表)】的数据库操作Service实现
 */
@Service
public class TRoleServiceImpl extends ServiceImpl<TRoleMapper, TRole>
        implements TRoleService {

    @Resource
    private TRoleResourceService roleResourceService;

    @Override
    public SaResult doSave(RoleDto roleDto) {
        if (existRoleName(roleDto.getName(), roleDto.getId(), false)) {
            return SaResult.error("角色名称已存在");
        }
        TRole role = new TRole();
        BeanUtils.copyProperties(roleDto, role);
        save(role);
        //新增角色关联的资源
        addResource(roleDto.getResourceList(), role.getId());
        return SaResult.ok("新增角色成功！");
    }

    @Override
    public SaResult doModify(RoleDto roleDto) {
        if (existRoleName(roleDto.getName(), roleDto.getId(), true)) {
            return SaResult.error("角色名称已存在！");
        }
        TRole role = new TRole();
        BeanUtils.copyProperties(roleDto, role);
        //删除原有角色资源关联
        removeResource(roleDto.getResourceList(), roleDto.getId());
        //新增角色关联的资源
        addResource(roleDto.getResourceList(), roleDto.getId());
        if (updateById(role)) {
            return SaResult.ok("修改角色成功！");
        }
        return SaResult.error("修改角色失败！");
    }

    @Override
    public SaResult doRemove(List<Long> ids) {
        for (Long roleId : ids) {
            QueryWrapper<TRole> roleQw = new QueryWrapper<>();
            roleQw.inSql("id", "select role_id from t_user group by role_id");
            List<TRole> roleList = list(roleQw);
            boolean hasUsed = false;
            for (TRole role : roleList) {
                for (Long id : ids) {
                    if (role.getId().equals(id)) {
                        hasUsed = true;
                        break;
                    }
                }
            }
            if (hasUsed) {
                return SaResult.error("角色下存在用户，不能删除！");
            } else {
                removeById(roleId);
                return SaResult.ok("删除角色成功！");
            }
        }
        return SaResult.error("删除角色失败！");
    }

    @Override
    public SaResult doList(RolePageDto pageDto) {
        IPage<TRole> rolePage = new Page<>(pageDto.getPageNo(), pageDto.getPageSize());
        IPage<RoleVo> roleVoPage = new Page<>(pageDto.getPageNo(), pageDto.getPageSize());
        lambdaQuery()
                .like(StrUtil.isNotEmpty(pageDto.getName()), TRole::getName, pageDto.getName())
                .eq(ObjectUtil.isNotNull(pageDto.getStatus()), TRole::getStatus, pageDto.getStatus())
                .page(rolePage);
        List<RoleVo> roleVoList = rolePage.getRecords().stream()
                .map(role -> {
                    RoleVo vo = convertRoleVo(role);
                    QueryWrapper<TRoleResource> roleResourceQw = new QueryWrapper<>();
                    //查询角色关联的资源
                    roleResourceQw.eq("role_id", Long.valueOf(role.getId()));
                    List<TRoleResource> roleResourceList = roleResourceService.list(roleResourceQw);
                    List<String> resourceIds = roleResourceList.stream()
                            .map(x -> String.valueOf(x.getResourceId()))
                            .collect(java.util.stream.Collectors.toList());
                    vo.setResourceList(resourceIds);
                    return vo;
                })
                .collect(java.util.stream.Collectors.toList());
        roleVoPage.setTotal(rolePage.getTotal());
        roleVoPage.setRecords(roleVoList);
        roleVoPage.setCurrent(rolePage.getCurrent());
        roleVoPage.setPages(rolePage.getPages());
        return SaResult.data(roleVoPage);
    }

    @Override
    public SaResult doAll() {
        List<TRole> roleList = list();
        List<RoleVo> roleVoList = roleList.stream()
                .map(role -> convertRoleVo(role))
                .collect(java.util.stream.Collectors.toList());
        return SaResult.data(roleVoList);
    }

    /**
     * 判断角色名称是否存在
     *
     * @param name
     * @return
     */
    private boolean existRoleName(String name, Long roleId, boolean isModify) {
        QueryWrapper<TRole> roleQw = new QueryWrapper<>();
        roleQw.eq("name", name);
        TRole dbRole = getOne(roleQw);
        if (!ObjectUtils.isEmpty(dbRole)) {
            if (!isModify) {
                return true;
            }
            if (!dbRole.getId().equals(roleId)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 转换为角色Vo对象
     *
     * @param role
     * @return
     */
    private RoleVo convertRoleVo(TRole role) {
        RoleVo roleVo = new RoleVo();
        BeanUtils.copyProperties(role, roleVo);
        roleVo.setId(String.valueOf(role.getId()));
        return roleVo;
    }

    /**
     * 删除角色关联的资源
     *
     * @param roleId
     */
    private void removeResource(List<Long> resourceIds, Long roleId) {
        QueryWrapper<TRoleResource> roleResourceQw = new QueryWrapper<>();
        roleResourceQw.eq("role_id", roleId);
        roleResourceService.remove(roleResourceQw);
    }

    /**
     * 新增角色关联的资源
     *
     * @param resourceIds
     * @param roleId
     */
    private void addResource(List<Long> resourceIds, Long roleId) {
        if (!ObjectUtils.isEmpty(resourceIds)) {
            List<TRoleResource> roleResourceList = resourceIds.stream().map(resourceId -> {
                TRoleResource roleResource = new TRoleResource();
                roleResource.setRoleId(roleId);
                roleResource.setResourceId(resourceId);
                return roleResource;
            }).collect(java.util.stream.Collectors.toList());
            roleResourceService.saveBatch(roleResourceList);
        }
    }
}




